package com.github.shiqiyue.myadmin.config.log4j.appender;

import org.apache.logging.log4j.core.Filter;
import org.apache.logging.log4j.core.Layout;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.appender.AbstractAppender;
import org.apache.logging.log4j.core.appender.AppenderLoggingException;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
import org.apache.logging.log4j.core.config.plugins.PluginElement;
import org.apache.logging.log4j.core.config.plugins.PluginFactory;
import org.apache.logging.log4j.core.layout.PatternLayout;

import java.io.Serializable;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/***
 * @see AbstractAppender 的实现
 *      <p>
 *      把系统日志信息放到队列里面，供系统其它部分使用
 *      </p>
 * @author wwy
 *
 */
@Plugin(name = "Queue", category = "Core", elementType = "appender", printObject = true)
public class QueueAppender extends AbstractAppender {
	
	private final ReadWriteLock rwLock = new ReentrantReadWriteLock();
	private final Lock readLock = rwLock.readLock();
	private static final Integer QUEUE_CAPACITY = 1000;
	private static BlockingQueue<String> queue = new ArrayBlockingQueue<>(QUEUE_CAPACITY);
	
	/***
	 * 需要实现的构造方法，直接使用父类就行
	 * 
	 * @param name
	 * @param filter
	 * @param layout
	 * @param ignoreExceptions
	 */
	protected QueueAppender(final String name, final Filter filter, final Layout<? extends Serializable> layout,
			final boolean ignoreExceptions) {
		super(name, filter, layout, ignoreExceptions);
	}
	
	@Override
	public void append(LogEvent event) {
		if (queue == null) {
			return;
		}
		readLock.lock();
		try {
			// 日志二进制文件，输出到指定位置就行
			final byte[] bytes = getLayout().toByteArray(event);
			// 下面这个是要实现的自定义逻辑
			String data = new String(bytes);
			while (!queue.offer(data)) {
				queue.poll();
			}
		} catch (Exception ex) {
			if (!ignoreExceptions()) {
				throw new AppenderLoggingException(ex);
			}
		} finally {
			readLock.unlock();
		}
	}
	
	/***
	 * 下面这个方法可以接收配置文件中的参数信息
	 * 
	 * @param name
	 * @param filter
	 * @param layout
	 * @param ignoreExceptions
	 * @return
	 */
	@PluginFactory
	public static QueueAppender createAppender(@PluginAttribute("name") String name,
			@PluginElement("Filter") final Filter filter,
			@PluginElement("Layout") Layout<? extends Serializable> layout,
			@PluginAttribute("ignoreExceptions") boolean ignoreExceptions) {
		if (name == null) {
			LOGGER.error("No name provided for MyCustomAppenderImpl");
			return null;
		}
		if (layout == null) {
			layout = PatternLayout.createDefaultLayout();
		}
		return new QueueAppender(name, filter, layout, ignoreExceptions);
	}
	
	public static String getLogItem() {
		String message;
		try {
			message = queue.take();
		} catch (InterruptedException e) {
			return null;
		}
		return message;
	}
	
}